package at.ac.tuwien.vpsbcm.spielzeugfabrik.alternativ.arbeiter;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import at.ac.tuwien.vpsbcm.spielzeugfabrik.alternativ.communication.LokTopicQueueConnHandler;
import at.ac.tuwien.vpsbcm.spielzeugfabrik.alternativ.teile.Holzgehaeuse;
import at.ac.tuwien.vpsbcm.spielzeugfabrik.alternativ.teile.Lokomotive;
import at.ac.tuwien.vpsbcm.spielzeugfabrik.alternativ.teile.Rad;
import at.ac.tuwien.vpsbcm.spielzeugfabrik.alternativ.teile.Schornstein;

public class Montage extends Arbeiter implements Runnable, MessageListener{
    
    private static int montageId;
    
    private List<Rad> raeder;
    private List<Holzgehaeuse> gehaeuse;
    private List<Schornstein> schornsteine;    

    private TopicPublisher topicPublisher;
    private Lokomotive lokomotive = null;
    private Teilecontainer teilecontainer;
    
    public Montage() throws JMSException {
        super();
        topicSubscriber = getLokTopicQueueConnHandler().getTopSubscriber();
        topicSubscriber.setMessageListener(this);
        topicPublisher = getLokTopicQueueConnHandler().getTopPublisher();
        System.out.println();

    }
    private synchronized boolean isLokomotiveAvailable() {
        return lokomotive != null;
    }
    
    private synchronized TopicPublisher getTopicPublisher() {
        return this.topicPublisher;
    }
    
    
    
    private synchronized void publish() throws JMSException {
        ObjectMessage messageOut = getTopicSession().createObjectMessage();
        messageOut.setStringProperty("bauteil","Lokomotive");
        messageOut.setStringProperty("lackiert", "ja");
        messageOut.setObject(lokomotive);
        topicPublisher.publish(messageOut);
        resetLokomotiveAvailability();
    }
    
    private  synchronized TopicSession getTopicSession() {
        return super.topicSession;
    }
    
    private synchronized void resetLokomotiveAvailability() {
        lokomotive = null;
    }

    public static void main(String[] args) {
        try {
            Random randomGenerator = new Random();
            montageId = randomGenerator.nextInt(100);
            Montage montage = new Montage();
            Thread t = new Thread(montage);
            t.start();
        } catch (JMSException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }      
    }

    public void run() {
        
        System.out.println("Ich bin ein Monteur mit der Nummer: " + montageId);
        while (true) {
               // System.out.println("monteur -> lokomotive: " + isLokomotiveAvailable());
                if (isLokomotiveAvailable()) {
    				try {
    					System.out.println("Monteur -> Die Lok wird versendet!");
    					publish();
    				} catch (JMSException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}                                 
                }             
        }       
    }
    
    public void onMessage(Message message) {
        ObjectMessage oMsg = null;     
        if (raeder == null) {
        	raeder = new ArrayList<Rad>();
        }
        if (gehaeuse == null) {
        	gehaeuse = new ArrayList<Holzgehaeuse>();
        }	
        if (schornsteine == null) {
        	schornsteine = new ArrayList<Schornstein>();
        }
        if (teilecontainer == null) {
            teilecontainer = new Teilecontainer();
        }
        try { 
          if (message instanceof ObjectMessage) {                
                oMsg = (ObjectMessage) message;
                if (oMsg.getStringProperty("bauteil").equals("Rad")) {
                    System.out.println("Monteur -> Reading message: " + ((Rad)oMsg.getObject()).getName() + ((Rad)oMsg.getObject()).getId());
                    Rad rad = (Rad)oMsg.getObject();
                    /*
                     * TODO: für ander beiden Teil auch implementieren
                     */
                    EindeutigesTeil teil = new EindeutigesTeil();
                    teil.setProduzentId(((Rad)oMsg.getObject()).getProduzentenId());
                    teil.setTeilId(((Rad)oMsg.getObject()).getId());
                    teil.setTeil(rad);
                    
//                    if (teilecontainer.checkTeilAvailability(teil) != true) {
//                        teilecontainer.addTeil(teil);
//                    }
                    /*
                     * TODO: Abfrage ob teil bereits in teilecontainer enthalten
                     * wenn nicht -> einfügen
                     * wenn schon -> löschen
                     */
                    
//                    rad.setVerwendet(true);
//                    if (raeder.size() < 6) {
//                        addRad(rad);
//                    } else {
//                        System.out.println("Es bereits " + raeder.size() + " Räder gespeichert!");
//                        buildLok();
//                        addRad(rad);
//                    }          
                    addRad(rad);
                }else if (oMsg.getStringProperty("bauteil").equals("Holzgehaeuse")){
                    System.out.println("Monteur -> Reading message: " + ((Holzgehaeuse)oMsg.getObject()).getName() + ((Holzgehaeuse)oMsg.getObject()).getId());
                    Holzgehaeuse holzgehaeuse = (Holzgehaeuse)oMsg.getObject();
                   
                    EindeutigesTeil teil = new EindeutigesTeil();
                    teil.setProduzentId(((Holzgehaeuse)oMsg.getObject()).getProduzentenId());
                    teil.setTeilId(((Holzgehaeuse)oMsg.getObject()).getId());
                    teil.setTeil(holzgehaeuse);
                    
//                    holzgehaeuse.setVerwendet(true);
//                    addHolzgehaeuse(holzgehaeuse);
                    addHolzgehaeuse(holzgehaeuse);
                }else if (oMsg.getStringProperty("bauteil").equals("Schornstein")) {
                    System.out.println("Monteur -> Reading message: " + ((Schornstein)oMsg.getObject()).getName() + ((Schornstein)oMsg.getObject()).getId());
                    Schornstein schornstein = (Schornstein)oMsg.getObject();
                    EindeutigesTeil teil = new EindeutigesTeil();
                    teil.setProduzentId(((Schornstein)oMsg.getObject()).getProduzentenId());
                    teil.setTeilId(((Schornstein)oMsg.getObject()).getId());
                    teil.setTeil(schornstein);
                    
                              
//                    teilecontainer.addTeil(teil);
//                    schornstein.setVerwendet(true);
                    addSchornstein(schornstein);                    
                }
            } else {
                System.out.println("Monteur -> Message of wrong type: " + message.getClass().getName());
            }
        } catch (JMSException e) {
            System.out.println("JMSException in onMessage(): " +
                e.toString());
        } catch (Exception e) {
            System.out.println("Exception in onMessage():" +
               e.getMessage());
           e.printStackTrace();
        }
    }
    
    private void addRad(Rad rad) {       
    	raeder.add(rad);         
    	if (checkBauteileList()) {
    		buildLok();
    	}
    }
    
    private void addHolzgehaeuse(Holzgehaeuse holzgehaeuse){
        gehaeuse.add(holzgehaeuse);
        if (checkBauteileList()) {
    		buildLok();
    	}
    }
    
    private void addSchornstein(Schornstein schornstein){
        schornsteine.add(schornstein);
        if (checkBauteileList()) {
    		buildLok();
    	}
    }
    
    private boolean checkBauteileList() {
    	return raeder.size() >= 6 && gehaeuse.size() >=1 && schornsteine.size() >= 1;
    }
    

	/**
	 * Nimm 6 Räder, 1 Gehäuse und 1 Schornstein
	 */
	private void buildLok() {

		
			lokomotive = new Lokomotive();
			lokomotive.setName("Lokomotive");
			Random randomGenerator = new Random();
			lokomotive.setId(randomGenerator.nextInt(100));
			int size = raeder.size();
			raeder.addAll(raeder.subList(0, size - 6));
			gehaeuse.remove(0);
			schornsteine.remove(0);
	}
    

}
